package com.ruoyi.file.utils;

import cn.hutool.core.codec.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.*;
import java.util.Random;

/**
 1) 加密算法：PBEWithMD5AndDES
 2) 迭代次数：1000
 */
public class FileEnPBE {

    public static void Encryption (String password,String s,String s2) throws Exception {
        //password为口令 ,s 为待加密数据,s2为用于存储加密后数据的文件

        char[] passwd=password.toCharArray( );				//由口令生成密钥
        PBEKeySpec pbks=new PBEKeySpec(passwd);
        SecretKeyFactory kf=SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey k=kf.generateSecret(pbks);

        byte[] salt=new byte[8];  							//生成随机数（盐）
        Random r=new Random( );
        r.nextBytes(salt);

        Cipher cp= Cipher.getInstance("PBEWithMD5AndDES");	//创建并初始化密码器
        PBEParameterSpec ps=new PBEParameterSpec(salt,1000);
        cp.init(Cipher.ENCRYPT_MODE, k,ps);

        byte ptext[]=s.getBytes("UTF8");					//获取明文，执行加密
        byte ctext[]=cp.doFinal(ptext);
        //将盐和加密结果合并在一起保存为密文
        FileOutputStream f=new FileOutputStream (s2 ) ;
        f.write (salt);
        f.write (ctext);									//打印盐的值
        System.out.println ("盐的值为：");
        for(int i=0 ; i<salt.length;i++){
            System.out.print (salt [ i] +" ");
        }
        System.out.println ("");
        System.out.println("加密结果为:");						//打印加密结果
        for(int i=0;i<ctext.length;i++){
            System.out.print (ctext [i] +" ");
        }

    }
    public static void Decryption (String password,String str2,String str3) throws Exception {
        //password为口令 ,str2为待解密的文件,str3为用于存储解密后数据的文件

        char[] passwd=password.toCharArray( );						//读取口令并生成密钥
        PBEKeySpec pbks=new PBEKeySpec(passwd);
        SecretKeyFactory kf=
                SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey k=kf.generateSecret(pbks);

        byte[] salt=new byte[8];									//获取随机数（盐）
        FileInputStream f=new FileInputStream(str2);
        f.read(salt);

        int num=f.available();										//获取加密结果
        byte[ ] ctext=new byte[num];
        f.read(ctext);

        Cipher cp=Cipher.getInstance("PBEWithMD5AndDES");			//创建密码器，执行解密
        PBEParameterSpec ps=new PBEParameterSpec(salt,1000);
        cp.init(Cipher.DECRYPT_MODE, k,ps);
        byte ptext[]=cp.doFinal(ctext);
        String p=new String(ptext ,"UTF8") ;
        System.out.println ("解密结果为：") ;
        System.out.println (p) ;									//输出解密结果

        FileOutputStream f2=new FileOutputStream (str3) ;			//存储解密结果到str3
//        f2.write (salt) ;
        f2.write(Base64.decode(ptext));

    }



    public static String Read (String str1)							//读取待加密文件
    {
        //String str1="C:/myjava/Hello.java";
        File file=new File(str1);
        //根据路径创建File类对象--这里路径即使错误也不会报错，因为只是产生File对象，还并未与计算机文件读写有关联
//        byte[] bytes=new byte[(int) file.length()];
        //根据文件的长度创建byte数组的长度
        try{
            FileInputStream fileInput=new FileInputStream(file);
            //与根据File类对象的所代表的实际文件建立链接创建fileInputStream对象
            try {
//                int data = fileInput.read(bytes,0,(int) file.length()) ;
//                String str=new String(bytes,0,data);
                String encode = Base64.encode(fileInput);
                return encode;
                //System.out.println(str);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e)
        {
            e.printStackTrace();
            System.out.println("文件不存在或者文件不可读或者文件是目录");
        }
        return null;
    }
}
